#ifndef DIGRAPH_H_
#define DIGRAPH_H_


/* Definicion del tipo de dato abstracto */

typedef struct digraphCDT * digraphADT;

/* Definicion de los elementos que contienen los nodos y las aristas */

typedef void * nodeT;	/* tipo de dato del nodo */ 
typedef void * edgeT;	/* tipo de dato de la arista */

/* Funciones callback necesarias para el digraphADT */

typedef int (* CmpNodesFn) (nodeT, nodeT);

/* Operaciones del ADT */

/*
* Funcion:			NewDiGraph
* Uso:				if ((digraph = NewDiGraph( cmpFn, nodeSize, EdgeSize )) == NULL); ...
*
*
* Descripcion:			Inicializa el digrafo y setea la funcion de comparacion "cmpFn"
*					para los elementos del nodo y el tamano de los elementos en los nodos
* 					y en las aristas que maneja el digrafo.
*						Es responsabilidad del usuario del ADT la correctitud de las mismas.
*					"cmpFn" compara dos elementos de tipo nodeT y debe 
*					devolver un numero < 0, == 0, > 0 si el primer elemento es menor, 
*					igual o mayor al segundo respectivamente.
*						Usar antes y por unica vez previo al resto de las operaciones del ADT.
* 					En caso de error, retorna NULL.
*		
* Precondicion:		Funcion de comparacion valida. Tamano del elemento > 0.
* Postcondicion:	digrafo creado.
*/

digraphADT NewDiGraph(CmpNodesFn cmpFn, int NodeSize, int EdgeSize);

/*
* Funcion:			DiGraphIsEmpty
* Uso:				if (DiGraphIsEmpty(digraph))...
*
*
* Descripcion:			Retorna un 1 si el digrafo no contiene ningun elemento,
* 					0 si los contiene y -1 si el digrafo a evaluar es inválido.
*		
* Precondicion:		digrafo valido
* Postcondicion:	digrafo invariable.
*/

int DiGraphIsEmpty(digraphADT digraph);

/*
* Funcion:			CreateNode
* Uso:				if (CreateNode(digraph, info))...
*
*
* Descripcion:			Retorna un 1 si se crea el nodo correctamente. 0 en caso
* 					contrario.
*		
* Precondicion:		digrafo valido
* Postcondicion:	Nodo creado cuya informacion almacenada es "info"
*/

int CreateNode(digraphADT digraph, nodeT info);

/*
* Funcion:			NodeBelongs
* Uso:				if (NodeBelongs(digraph, info))...
*
*
* Descripcion:			Retorna un 1 si el nodo que contiene almacenado el elemento "info,
* 					pertenece al digrafo, 0 en caso contrario.
*		
* Precondicion:		digrafo y nodo a evaluar validos.
* Postcondicion:	digrafo invariable.
*/

int NodeBelongs(digraphADT digraph, nodeT info);

/*
* Funcion:			NodeCount
* Uso:				int cant;
* 					cant = NodeCount(digraph);
*
*
* Descripcion:			Retorna la cantidad de nodos en el digrafo
*		
* Precondicion:		digrafo valido
* Postcondicion:	digrafo invariable.
*/

int NodeCount(digraphADT digraph);


/*
* Funcion:			InputEdges
* Uso:				iedges = InputEdges(digraph, node);
*
*
* Descripcion:			Retorna la cantidad de aristas que "entran" al nodo
* 					En caso de error, retorna -1
*		
* Precondicion:		digrafo y nodo validos
* Postcondicion:	digrafo invariante
*/

int InputEdges(digraphADT digraph, nodeT node);

/*
* Funcion:			OutputEdges
* Uso:				oedges = OutputEdges(digraph, node);
*
*
* Descripcion:			Retorna la cantidad de aristas que "salen" del nodo
* 					En caso de error, retorna -1
*		
* Precondicion:		digrafo y nodo validos
* Postcondicion:	digrafo invariante
*/

int OutputEdges(digraphADT digraph, nodeT info);

/*
* Funcion:			DeleteNode
* Uso:				if (DeleteNode(digraph, info))...
*
*
* Descripcion:			Retorna un 1 si el nodo que contiene almacenado el elemento "info,
* 					fue borrado efectivamente, o 0 en caso contrario.
*		
* Precondicion:		digrafo y nodo a evaluar válidos.
* Postcondicion:	Nodo eliminado
*/

int DeleteNode(digraphADT digraph, nodeT info);

/*
* Funcion:			CreateEdge
* Uso:				if (CreateEdge(digraph, srcinfo, tgtinfo, edgeinfo))...
*
*
* Descripcion:			Retorna un 1 si pudo crear una arista entre el nodo src y tgt.
* 					Si alguno de los nodos "src" o "tgt" no existia previamente, se lo crea.
* 					Ademas almacena en la arista el elemento "edgeElement". En caso de falla por
* 					falta de memoria o error de algun tipo retorna 0.
*		
* Precondicion:		digrafo y elemento de la arista a crear validos
* Postcondicion:	arco creado entre los nodos "src" y "tgt"
*/

int CreateEdge(digraphADT digraph, nodeT src, nodeT tgt, edgeT edgeElement);

/*
* Funcion:			GetEdge
* Uso:				if (GetEdge(digraph, srcnode, tgtnode, &edgeElement))...
*
*
* Descripcion:			Retorna un 1 si encuentra la arist entre "src" y "tgt"
* 					devolviendo en el parametro edgeElement dicha arista. Devuelve la original
* 					por lo tanto, en caso de modificacion, se modificará en el digrafo.
* 					Caso contrario retorna 0 y NULL en "edgeElement".
*		
* Precondicion:		digrafo, nodos a evaluar validos.
* Postcondicion:	digrafo invariable.
*/

int GetEdge(digraphADT digraph, nodeT src, nodeT tgt, edgeT * edgeElement);

/*
* Funcion:			DeleteEdge
* Uso:				if (GetEdge(digraph, srcnode, tgtnode, &edgeElement))...
*
*
* Descripcion:			Retorna un 1 si encuentra la arist entre "src" y "tgt"
* 					y logra devolver la variable previamente reservada en heap o stack
* 					"edgeElement", la informacion de dicha arista. Caso contrario retorna 0
* 					y NULL en "edgeElement".
*		
* Precondicion:		digrafo, nodos a evaluar validos. Memoria previamente reservada para "edgeElement"
* Postcondicion:	digrafo invariable.
*/

int DeleteEdge(digraphADT digraph, nodeT src, nodeT tgt);


/*
* Funcion:			SetIteratorEdge
* Uso:				SetIteratorEdge(digraph, src)
*
*
* Descripcion:			Inicializa el iterador para iterar por las adyacencias del nodo "src".
*		
* Precondicion:		digrafo y nodo "src" válidos 
* Postcondicion:	digrafo invariante.
*/


int SetIteratorEdge(digraphADT digraph, nodeT src);

/*
* Funcion:			GetNextEdge
* Uso:				edgeT aux;
* 					edge = GetNextEdge(digraph)
*
*
* Descripcion:			Dado un nodo "src", devuelve la próxima arista en la lista
* 					de adyacencias en el parámetro aim, y retorna el nodo al que dicha
* 					arista apunta en el parámetro node. Devuelve un 1 si la función tuvo éxito
* 					y 0 si ya se iteró por todas las aristas del nodo src. Esta funcion devuelve
* 					los elementos originales del digrafo, por lo tanto es solo de consulta, si se modifica
* 					se modificará a su vez en el digrafo.
*		
* Precondicion:		digrafo y nodo "src" válidos. 
* Postcondicion:	digrafo invariante.
*/

int GetNextEdge(digraphADT digraph, nodeT src, edgeT * aim, nodeT * node);

/*
* Funcion:			EdgeCount
* Uso:				int cantEdge;
* 					cantEdge = EdgeCount(digraph);
*
*
* Descripcion:			Retorna la cantidad de aristas en el digrafo.
*		
* Precondicion:		digrafo valido
* Postcondicion:	digrafo invariable.
*/

int EdgeCount(digraphADT digraph);

/*
* Funcion:			IsConnected
* Uso:				if (IsConnected(digraph, srcnode, tgtnode))...
*
*
* Descripcion:			Retorna un 1 si existe una arista que conecta al nodo
* 					"src" con "tgt", recordar que el orden es importante ya que
* 					se trata de un digrafo. Caso contrario retorna 0
*		
* Precondicion:		digrafo, nodos a evaluar validos.
* Postcondicion:	digrafo invariable.
*/

int IsConnected(digraphADT digraph, nodeT src, nodeT tgt);

/*
* Funcion:			
* Uso:				SetIteratorBFS(digraph);
*
*
* Descripcion:			Inicializa al digrafo para iterar por los nodos en BFS a
* 					partir del nodo inicial indicado por "start". Si se produce algún
* 					tipo de error en la inicializacion, retorna 0, caso contrario 1.
* 					Esta funcion se debe invocar antes y una vez por instancia (es decir por cada
* 					recorrido diferente a realizarse), que GetNodeBFS
*		
* Precondicion:		digrafo y nodo por donde se comienza a iterar valido.
* Postcondicion:	digrafo invariante.
*/

int SetIteratorBFS(digraphADT digraph, nodeT start);

/*
* Funcion:			
* Uso:				GetNextNodeBFS(digraph);
*
*
* Descripcion:			Devuelve el proximo contenido de un nodo, en la iteracion BFS del digrafo.
* 					Cuando devuelve NULL, significa que se termino el recorrido. El primer nodo en el
* 					recorrido fue seteado por la funcion "SetIteratorBFS". El contenido devuelto NO debe
* 					ser alterado, su unico fin es de consulta.
*		
* Precondicion:		digrafo valido. SetIteratorBFS invocada exitosamente previamente.
* Postcondicion:	digrafo invariante.
*/

nodeT GetNextNodeBFS(digraphADT digraph);

/*
* Funcion:			
* Uso:				FreeDiGraph(digraph);
*
*
* Descripcion:			Destruye completamente el digrafo. Una vez realizado no podra
* 					recuperarse el digrafo. Usar unicamente cuando no se necesite utilizar
* 					mas el digrafo para ningun tipo de operacion
*		
* Precondicion:		digrafo valido.
* Postcondicion:	digrafo eliminado.
*/

void FreeDiGraph(digraphADT digraph);


/*para iterar por los nodos */

void SetBeginDiGraph( digraphADT digraph );

nodeT GetNextNode( digraphADT digraph );

int IsLastNode( digraphADT digraph, nodeT node );

#endif /*DIGRAPH_H_*/
